﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Marmat.Foundation;
using Marmat.FrameWork;

namespace Marmat.Template.WinForm
{
    public partial class PermissionManagerForm : Marmat.Forms.Form, Marmat.Foundation.IPermissionManagerForm, IProvider
    {
        private readonly IPermissionManager permissionManager;
        private readonly IPermissionMenuManager menuManager;

        /// <summary>
        /// 内置的管理员组
        /// </summary>
        PermissionRoleEntity system_role;
        /// <summary>
        /// 内置的分组
        /// </summary>
        PermissionRoleEntity default_role_group;
        /// <summary>
        /// 当前选中的角色
        /// </summary>
        IRoleEntity selectionRole;
        /// <summary>
        /// 加载中
        /// </summary>
        bool loading = false;

        /// <summary>
        /// 存储角色设置按钮区域的图标。
        /// </summary>
        Dictionary<IRoleEntity, Rectangle> settingRectangleCollection = new Dictionary<IRoleEntity, Rectangle>();


        void IPermissionManagerForm.Show()
        {
            this.ShowDialog();
        }

        public PermissionManagerForm()
        {
            InitializeComponent();
            this.permissionManager = SystemCommand.GetService<IPermissionManager>();
            this.menuManager = SystemCommand.GetService<IPermissionMenuManager>();
        }


        private int SelectionPanelIndex
        {
            get => selectionPanelIndex;
            set
            {
                selectionPanelIndex = value;
                Panel panel = null;
                Label label = null;
                switch (value)
                {
                    case 0:
                        label = this.label1;
                        panel = this.panel3;
                        break;
                    case 1:
                        label = this.label2;
                        panel = this.panel4;
                        break;
                    case 2:
                        label = this.label3;
                        panel = this.panel5;
                        break;
                }
                this.panel3.Visible = panel == this.panel3;
                this.panel4.Visible = panel == this.panel4;
                this.panel5.Visible = panel == this.panel5;
                panel.BringToFront();
                this.label1.Font = new Font(this.label1.Font, label == this.label1 ? FontStyle.Underline | FontStyle.Bold : FontStyle.Regular);
                this.label2.Font = new Font(this.label2.Font, label == this.label2 ? FontStyle.Underline | FontStyle.Bold : FontStyle.Regular);
                this.label3.Font = new Font(this.label3.Font, label == this.label3 ? FontStyle.Underline | FontStyle.Bold : FontStyle.Regular);
            }
        }

        private void PermissionForm_Load(object sender, EventArgs e)
        {
            var roleCollection = permissionManager.GetRoleCollection();
            var menuCollection = this.menuManager?.GetMenuCollection();

            default_role_group = new PermissionRoleEntity();
            default_role_group.IsGroup = true;
            default_role_group.Name = "默认分组";
            default_role_group.Text = "默认分组";
            var group = this.treeView1.Nodes.Add("默认分组");
            group.Tag = default_role_group;

            var system_node = group.Nodes.Add("admin", "系统管理员");
            system_role = new PermissionRoleEntity();
            system_role.Name = "admin";
            system_role.Text = "系统管理员";
            system_node.Tag = system_role;
            this.treeView1.SelectedNode = system_node;
            treeView1_AfterSelect(this.treeView1, new Forms.Skin.TreeViewEventArgs(system_node));

            buildRole(this.treeView1.Nodes, roleCollection.Where(x => string.IsNullOrEmpty(x.Parent)));
            this.treeView1.ExpandAll();

            if (menuCollection is not null)
            {
                buildMenu(this.treeView3.Nodes, menuCollection.Where(x => string.IsNullOrEmpty(x.Parent)));
                this.treeView3.ExpandAll();
            }

            var permissionCollection = permissionManager.GetPermissionCollection();
            foreach (var permission in permissionCollection)
            {
                string[] pathCollection = (permission.Path ?? "").Split('/').Where(x => !string.IsNullOrEmpty(x)).ToArray();
                Marmat.Forms.Skin.TreeNodeCollection nodeCollection = this.treeView2.Nodes;
                if (pathCollection.Length > 0)
                {
                    foreach (var path in pathCollection)
                    {
                        if (nodeCollection.ContainsKey(path))
                            nodeCollection = nodeCollection[path].Nodes;
                        else
                        {
                            var treeNode = nodeCollection.Add(path, path);
                            treeNode.NodeFont = new Font(this.treeView2.Font, FontStyle.Italic);
                            nodeCollection = treeNode.Nodes;
                        }
                    }
                }
                var node = nodeCollection.Add(permission.Name, permission.Text);
                node.Tag = permission;
            }
            this.treeView2.ExpandAll();

            void buildRole(Marmat.Forms.Skin.TreeNodeCollection nodes, IEnumerable<IRoleEntity> roles)
            {
                foreach (var role in roles)
                {
                    var node = new Forms.Skin.TreeNode();
                    node.Name = role.Name;
                    node.Text = role.Text;
                    node.Tag = role;
                    nodes.Add(node);
                    buildRole(node.Nodes, roleCollection.Where(x => x.Parent == role.Name));
                }
            }

            void buildMenu(Marmat.Forms.Skin.TreeNodeCollection nodes, IEnumerable<IMenu> menus)
            {
                foreach (var menu in menus)
                {
                    var node = new Forms.Skin.TreeNode();
                    node.Name = menu.Name;
                    node.Text = menu.Text;
                    node.Tag = menu;
                    nodes.Add(node);
                    buildMenu(node.Nodes, menuCollection.Where(x => x.Parent == menu.Name));
                }
            }
        }

        private void treeView1_DrawNode(object sender, Forms.Skin.DrawTreeNodeEventArgs e)
        {
            Color backColor = Color.Transparent;
            if (e.Node == this.treeView1.SelectedNode)
                backColor = Color.FromArgb(179, 224, 255);
            else if (e.Node == this.treeView1.MouseMoveNode)
                backColor = Color.FromArgb(226, 240, 255);
            using SolidBrush brush = new SolidBrush(backColor);
            e.Graphics.FillRectangle(brush, e.Bounds);
            int left = e.Node.Level * this.treeView1.Indent + 12;

            Image img;
            if (e.Node.Nodes.Count > 0)
            {
                if (e.Node.IsExpanded)
                    img = Properties.Resources.expand_icon;
                else
                    img = Properties.Resources.collapse_icon;
                e.Graphics.DrawImage(img, new Rectangle(left, e.Bounds.Top + (e.Bounds.Height - img.Height) / 2, img.Width, img.Height), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
            }
            left += 30;
            Rectangle bounds = new Rectangle(left, e.Bounds.Y, this.treeView1.ClientSize.Width - left - 1, e.Bounds.Height);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, this.treeView1.Font, bounds, Color.Black, Color.Transparent, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
            if (this.treeView1.SelectedNode == e.Node && e.Node.Tag != system_role && e.Node.Tag != default_role_group)
            {
                img = Properties.Resources.setting_icon;
                bounds = new Rectangle(bounds.Right - img.Width - 6, bounds.Top + (bounds.Height - img.Height) / 2, img.Width, img.Height);
                this.settingRectangleCollection[e.Node.Tag as IRoleEntity] = bounds;
                e.Graphics.DrawImage(img, bounds);
            }
        }

        private void treeView1_MeasureNode(object sender, Forms.Skin.MeasureTreeNodeEventArgs e)
        {
            e.Size = new Size(this.treeView1.Width, e.Size.Height);
        }

        private void treeView1_NodeMouseClick(object sender, Marmat.Forms.Skin.TreeNodeMouseClickEventArgs e)
        {
            var settingNode = settingRectangleCollection.FirstOrDefault(x => x.Value.Contains(e.Location)).Key;
            if (settingNode is not null)
            {
                this.contextMenuStrip1.Tag = e.Node;
                if (e.Node.Tag is IRoleEntity role)
                    this.添加角色ToolStripMenuItem.Visible = role.IsGroup;
                this.contextMenuStrip1.Show(this.treeView1, e.Location);
                return;
            }
            if (e.Node.Nodes.Count > 0)
            {
                if (e.Node.IsExpanded)
                    e.Node.Collapse();
                else
                    e.Node.Expand();
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {
            this.SelectionPanelIndex = 0;
        }

        private void label2_Click(object sender, EventArgs e)
        {
            this.SelectionPanelIndex = 1;
        }

        private void label3_Click(object sender, EventArgs e)
        {
            this.SelectionPanelIndex = 2;
        }

        private void treeView1_AfterSelect(object sender, Forms.Skin.TreeViewEventArgs e)
        {
            if (e.Node.Tag is Marmat.Foundation.IRoleEntity role && !role.IsGroup)
            {
                this.loading = true;
                try
                {
                    this.Text = $"权限管理 - {role.Text}";
                    this.selectionRole = role;
                    IEnumerable<IUserEntity> userCollection = null;
                    IEnumerable<IPermissionEntity> permissionCollection = null;
                    IEnumerable<IMenu> menuCollection = null;
                    if (role == system_role)
                    {
                        switchPage("admin");
                        userCollection = this.permissionManager.GetAdminUserCollection();
                    }
                    else
                    {
                        switchPage("");
                        userCollection = this.permissionManager.GetRoleUserCollection(role.Name);
                        menuCollection = this.menuManager?.GetRoleMenuCollection(role.Name);
                        permissionCollection = this.permissionManager.GetRolePermissionCollection(role.Name);
                    }

                    // 更新角色对应的用户列表UI。
                    this.permissionFormUserControl1.SetUserCollection(userCollection);

                    // 更新角色对应的权限列表UI。
                    GetAllNodeCollection(this.treeView2.Nodes).ForEach(node =>
                    {
                        if (node.Tag is null)
                            node.Checked = false;
                        else if (node.Tag is IPermissionEntity permission)
                            node.Checked = permissionCollection?.FirstOrDefault(p => p.Name == permission.Name) is not null;
                    });
                    // 更新角色对应的权限列表UI。
                    GetAllNodeCollection(this.treeView3.Nodes).ForEach(node =>
                    {
                        if (node.Tag is null)
                            node.Checked = false;
                        else if (node.Tag is IMenu menu)
                            node.Checked = menuCollection?.FirstOrDefault(p => p.Name == menu.Name) is not null;
                    });
                }
                finally
                {
                    this.loading = false;
                }
            }
        }

        private string pageName;
        private int selectionPanelIndex;

        public List<Marmat.Forms.Skin.TreeNode> GetAllNodeCollection(Marmat.Forms.Skin.TreeNodeCollection nodes)
        {
            List<Marmat.Forms.Skin.TreeNode> items = new List<Forms.Skin.TreeNode>();
            foreach (Marmat.Forms.Skin.TreeNode node in nodes)
            {
                items.Add(node);
                if (node.Nodes.Count > 0)
                    items.AddRange(GetAllNodeCollection(node.Nodes));
            }
            return items;
        }

        private void switchPage(string pageName)
        {
            this.pageName = pageName;
            try
            {
                Marmat.Forms.WindowsAPI.LockWindowUpdate(this.Handle.ToInt32());
                switch (pageName)
                {
                    case "admin":
                        this.label1.Visible = false;
                        this.label2.Visible = false;
                        this.label3.Visible = false;
                        this.label2.Enabled = true;
                        this.SelectionPanelIndex = 1;
                        break;
                    case "default":
                        this.label1.Visible = true;
                        this.label2.Visible = true;
                        this.label3.Visible = true;
                        this.label2.Enabled = false;
                        this.label3.Enabled = true;
                        if (this.SelectionPanelIndex == 1)
                            this.SelectionPanelIndex = 0;
                        break;
                    case "":
                        this.label1.Visible = true;
                        this.label2.Visible = true;
                        this.label3.Visible = true;
                        this.label2.Enabled = true;
                        this.label3.Enabled = true;
                        break;
                }
                this.label4.Visible = pageName == "admin";
                this.label5.Visible = pageName == "admin";
            }
            finally
            {
                Marmat.Forms.WindowsAPI.LockWindowUpdate(IntPtr.Zero.ToInt32());
            }
        }

        /// <summary>
        /// 点击添加用户时发生。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void permissionFormUserControl1_AddUsering(object sender, EventArgs e)
        {
            var role = this.selectionRole;
            if (role is not null)
            {
                ISelectionUserForm frm = SystemCommand.GetService<ISelectionUserForm>();
                List<IUserEntity> old_collection = this.permissionFormUserControl1.users.ToList();
                List<IUserEntity> collection = old_collection.ToList();
                if (frm.ShowDialog(collection))
                {
                    var deleteCollection = old_collection.Where(item => !collection.Exists(x => x.UserID == item.UserID)).Where(x => !string.IsNullOrEmpty(x.UserID));
                    var addCollection = collection.Where(item => !old_collection.Exists(x => x.UserID == item.UserID)).Where(x => !string.IsNullOrEmpty(x.UserID));
                    if (role == this.system_role)
                    {
                        if (deleteCollection.Count() > 0)
                            this.permissionManager.RemoveAdminUserCollection(deleteCollection.Select(x => x.UserID).ToArray());
                        if (addCollection.Count() > 0)
                            this.permissionManager.AddAdminUserCollection(addCollection.Select(x => x.UserID).ToArray());
                    }
                    else
                    {
                        if (deleteCollection.Count() > 0)
                            this.permissionManager.RemoveRoleUserCollection(role.Name, deleteCollection.Select(x => x.UserID).ToArray());
                        if (addCollection.Count() > 0)
                            this.permissionManager.AddRoleUserCollection(role.Name, addCollection.Select(x => x.UserID).ToArray());
                    }
                    this.permissionFormUserControl1.SetUserCollection(collection);
                }
            }
        }

        /// <summary>
        /// 移除用户
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void permissionFormUserControl1_DeleteUsering(object sender, IUserEntity e)
        {
            var role = this.selectionRole;
            if (role is not null)
            {
                if (role == this.system_role)
                    this.permissionManager.RemoveAdminUserCollection(new string[] { e.UserID });
                else
                    this.permissionManager.RemoveRoleUserCollection(role.Name, new string[] { e.UserID });
                this.permissionFormUserControl1.Remove(e);
            }
        }

        private void treeView2_BeforeCheck(object sender, Forms.Skin.TreeViewCancelEventArgs e)
        {
            if (e.Node.Tag is null)
                e.Cancel = true;
        }

        /// <summary>
        /// 选择或取消选择后触发的事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView2_AfterCheck(object sender, Forms.Skin.TreeViewEventArgs e)
        {
            if (this.loading) return;

            var role = this.selectionRole;
            if (role is not null && e.Node.Tag is IPermissionEntity permission)
            {
                if (e.Node.Checked)
                    this.permissionManager.AddRolePermissionCollection(role.Name, new string[] { permission.Name });
                else
                    this.permissionManager.RemoveRolePermissionCollection(role.Name, new string[] { permission.Name });
            }
        }
        private void treeView3_AfterCheck(object sender, Forms.Skin.TreeViewEventArgs e)
        {
            if (this.loading) return;
            var role = this.selectionRole;
            if (role is not null && e.Node.Tag is IMenu menu)
            {
                if (e.Node.Checked)
                    this.menuManager.AddRoleMenuCollection(role.Name, new string[] { menu.Name });
                else
                    this.menuManager.RemoveRoleMenuCollection(role.Name, new string[] { menu.Name });
                if (e.Node.Checked && e.Node.Parent is not null)
                    e.Node.Parent.Checked = true;
            }
        }

        /// <summary>
        /// 创建组
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void skinButton2_Click(object sender, EventArgs e)
        {
            string groupName = "";
            if (Marmat.Forms.InputValue.Show(ref groupName, "新建角色组", "清输入分组的名称：") && !string.IsNullOrEmpty(groupName))
            {
                var item = this.permissionManager.CreateRoleGroup(groupName);
                var group = this.treeView1.Nodes.Add(item.Name, item.Text);
                group.Tag = item;
                this.treeView1.SelectedNode = group;
            }
        }

        /// <summary>
        /// 新建角色
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void skinButton1_Click(object sender, EventArgs e)
        {
            CreateRoleForm frm = new CreateRoleForm();
            if (frm.ShowDialog() == DialogResult.OK)
            {
                if (frm.comboBox1.Value is IRoleEntity group)
                {
                    var role = this.permissionManager.CreateRole(group.Name, frm.textBox1.Value);
                    var node = this.treeView1.Nodes.OfType<Marmat.Forms.Skin.TreeNode>().FirstOrDefault(x => x.Tag is IRoleEntity item && item.Name == group.Name);
                    if (node is not null)
                    {
                        var item = new Marmat.Forms.Skin.TreeNode();
                        item.Name = role.Name;
                        item.Text = role.Text;
                        item.Tag = role;
                        node.Nodes.Add(item);
                        this.treeView1.SelectedNode = item;
                    }
                }
            }
        }

        private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Name)
            {
                case nameof(添加角色ToolStripMenuItem):
                    {
                        if (this.contextMenuStrip1.Tag is Marmat.Forms.Skin.TreeNode node && node.Tag is IRoleEntity role && role.IsGroup)
                        {
                            CreateRoleForm frm = new CreateRoleForm();
                            frm.comboBox1.SelectedValue = role;
                            if (frm.ShowDialog() == DialogResult.OK)
                            {
                                if (frm.comboBox1.Value is IRoleEntity group)
                                {
                                    var item_role = this.permissionManager.CreateRole(group.Name, frm.textBox1.Value);
                                    var item_node = this.treeView1.Nodes.OfType<Marmat.Forms.Skin.TreeNode>().FirstOrDefault(x => x.Tag is IRoleEntity item && item.Name == group.Name);
                                    if (item_node is not null)
                                    {
                                        var item = new Marmat.Forms.Skin.TreeNode();
                                        item.Name = item_role.Name;
                                        item.Text = item_role.Text;
                                        item.Tag = item_role;
                                        item_node.Nodes.Add(item);
                                        this.treeView1.SelectedNode = item;
                                    }
                                }
                            }
                        }
                    }
                    break;
                case nameof(重命名ToolStripMenuItem):
                    {
                        if (this.contextMenuStrip1.Tag is Marmat.Forms.Skin.TreeNode node && node.Tag is IRoleEntity role)
                        {
                            string name = role.Text;
                            if (Marmat.Forms.InputValue.Show(ref name, "重命名", "请重新输入名称：") && !string.IsNullOrEmpty(name))
                            {
                                this.permissionManager.ReNameRole(role.Name, name);
                                role.Text = name;
                                node.Text = name;
                            }
                        }
                    }
                    break;
                case nameof(删除ToolStripMenuItem):
                    {
                        if (this.contextMenuStrip1.Tag is Marmat.Forms.Skin.TreeNode node && node.Tag is IRoleEntity role)
                        {
                            if (Marmat.Forms.MessageBox.Show($"删除“{role.Text}”，组内角色与相关人的角色信息都将清空。是否继续删除？", $"确认要删除“{role.Text}”吗？", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                            {
                                List<string> userCollection = new List<string>();
                                userCollection.Add(role.Name);
                                if (node.Nodes.Count > 0)
                                    this.GetAllNodeCollection(node.Nodes).Select(x => (x.Tag as IRoleEntity).Name).ToList().ForEach(x => userCollection.Add(x));
                                this.permissionManager.DeleteRole(userCollection.ToArray());
                                this.treeView1.SelectedNode = node.PrevNode;
                                node.Remove();
                            }
                        }
                    }
                    break;
            }
        }


    }
}